﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MvcEngine.Core.Services;
using System.Web.Mvc;
using MvcEngine.Mvc.Extensions;
using MvcEngine.Blog.Components.Services;
using MvcEngine.Mvc.Constraints;
using MvcEngine.Blog.BackOffice.Controllers;
using MvcEngine.Mvc;
using MvcEngine.Core;
using MvcEngine.Blog.Commands;
using MvcEngine.Core.Registry;
using MvcEngine.Blog.ModelBinders;
using MvcEngine.Blog.Models.Entities;
using MvcEngine.Blog.Filters;
using MvcEngine.Mvc.Filters;
using MvcEngine.Blog.BackOffice.Filters;
using MvcEngine.Mvc.Services;

namespace MvcEngine.Blog.Services
{
    public class PostControlService : ControlServiceBase
    {
        public override void RegisterBackofficeRoutes(AreaRegistrationContext context)
        {
            context.MapMvcEngineRoute(
                "BackOffice_Blog",
                "BackOffice/Blog/{blogName}",
                new { controller = "BlogPost", action = "List" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogPostList",
                "BackOffice/Blog/{blogName}/Posts",
                new { controller = "BlogPost", action = "List" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogPostPageIndex",
                "BackOffice/Blog/{blogName}/Posts/Page{pageNumber}",
                new { controller = "BlogPost", action = "List", pageNumber = "0" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogPostEdit",
                "BackOffice/Blog/{blogName}/Post/Edit/{postId}",
                new { controller = "BlogPost", action = "Edit" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogPostNew",
                "BackOffice/Blog/{blogName}/Post/New",
                new { controller = "BlogPost", action = "Edit" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogPostDelete",
                "BackOffice/Blog/{blogName}/Post/Delete/{postId}",
                new { controller = "BlogPost", action = "Delete" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_NewPostUploadFile",
                "BackOffice/Blog/{blogName}/UploadFile",
                new { controller = "BlogPost", action = "UploadFile" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_EditPostUploadFile",
                "BackOffice/Blog/{blogName}/UploadFile/Post/{postId}",
                new { controller = "BlogPost", action = "UploadFile" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            #region Comment routes

            context.MapMvcEngineRoute(
                "BackOffice_BlogCommentDelete",
                "BackOffice/Blog/{blogName}/Comment/Delete/{commentId}",
                new { controller = "BlogPost", action = "DeleteComment" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BackOffice_BlogComments",
                "BackOffice/Blog/{blogName}/Comments",
                new { controller = "BlogPost", action = "Comments" },
                new string[] { "MvcEngine.Blog.BackOffice.Controllers" }
            );

            #endregion
        }

        public override void RegisterStarterSiteRoutes(AreaRegistrationContext context)
        {
            context.MapModuleRoute(
                "BlogPostIndex",
                "{pageName}/Posts",
                new { actionName = "Index" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapModuleRoute(
                "BlogPostPageIndex",
                "{pageName}/Posts/{pageNumber}",
                new { actionName = "Index" },
                new { pageNumber = new IntegerConstraint() },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapModuleRoute(
                "BlogPostDetailsId",
                "{pageName}/Post/{postId}",
                new { actionName = "PostDetails" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapModuleRoute(
                "BlogPostDetails",
                "{pageName}/Post/{year}/{month}/{day}/{postName}",
                new { actionName = "Details" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapImageRoute(
                "BlogPostFile",
                "{pageName}/PostFile/{year}/{month}/{fileName}",
                new BlogFileResolver(),
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapMvcEngineRoute(
                "BlogPostRss",
                "{pageName}/Posts/Rss",
                new { controller = "BlogPost", action = "Rss" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );


            context.MapModuleRoute(
                "BlogCategoryFilterPage",
                "{pageName}/category/{categoryName}/Page{pageNumber}",
                new { actionName = "CategoryFilter" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapModuleRoute(
                "BlogCategoryFilter",
                "{pageName}/category/{categoryName}",
                new { actionName = "CategoryFilter" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            #region Tag routes

            context.MapModuleRoute(
                "BlogTagFilterPage",
                "{pageName}/tag/{tagName}/Page{pageNumber}",
                new { actionName = "TagFilter" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            context.MapModuleRoute(
                "BlogTagFilter",
                "{pageName}/tag/{tagName}",
                new { actionName = "TagFilter" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            #endregion

            #region Comment routes

            context.MapModuleRoute(
                "BlogCommentCreate",
                "{pageName}/Comments/Create",
                new { actionName = "CreateComment" },
                new string[] { "MvcEngine.Blog.StarterSite.Controllers" }
            );

            #endregion
        }

        public override IList<ControlCommand> GetCommands()
        {
            var commands = new List<ControlCommand>();

            commands.Add(new NewPostCommand() { Name = "New", LocalizedName = "New" });
            commands.Add(new PostListCommand() { Name = "List", LocalizedName = "Posts" });

            return commands;
        }

        public override IEnumerable<string> GetStyleSheets()
        {
            return new List<string>() { "shCore.css" };
        }

        public override void RegisterActionFilters(IActionFilterRegistry registry)
        {
            //--------------------------------------------------------------------------------------
            //------------------------------Common filters------------------------------------------
            //--------------------------------------------------------------------------------------
            ControllerCriteria backOfficeCommonCriteria = new ControllerCriteria();
            backOfficeCommonCriteria.AddController(typeof(MvcEngine.Blog.BackOffice.Controllers.BlogPostController));
            registry.Add(new[] { backOfficeCommonCriteria }, typeof(PostActionFilter));
            registry.Add(new[] { backOfficeCommonCriteria }, typeof(MvcEngine.Blog.BackOffice.Filters.BlogActionFilter));

            ControllerCriteria starterSiteCommonCriteria = new ControllerCriteria();
            starterSiteCommonCriteria.AddController(typeof(MvcEngine.Blog.StarterSite.Controllers.BlogPostController));
            registry.Add(new[] { starterSiteCommonCriteria }, typeof(MvcEngine.Blog.StarterSite.Filters.BlogActionFilter));
            //--------------------------------------------------------------------------------------
            //------------------------------End of common filters-----------------------------------
            //--------------------------------------------------------------------------------------

            ControllerActionCriteria commentsCriteria = new ControllerActionCriteria();
            commentsCriteria.AddAction<MvcEngine.Blog.StarterSite.Controllers.BlogPostController>(a => a.Details(Guid.Empty, null));
            commentsCriteria.AddAction<MvcEngine.Blog.StarterSite.Controllers.BlogPostController>(a => a.CreateComment(Guid.Empty, Guid.Empty, false, null));
            commentsCriteria.AddAction<MvcEngine.Blog.StarterSite.Controllers.BlogPostController>(a => a.PostDetails(Guid.Empty));
            registry.Add(new[] { commentsCriteria }, typeof(PostDetailsFilter));

            //Rss
            ControllerActionCriteria rssCriteria = new ControllerActionCriteria();
            rssCriteria.AddAction<MvcEngine.Blog.StarterSite.Controllers.BlogPostController>(a => a.Rss(Guid.Empty));
            registry.Add(new[] { rssCriteria }, typeof(PageActionFilter));
            registry.Add(new[] { rssCriteria }, typeof(RssActionFilter));

            //Overview
            //ControllerActionCriteria overviewCriteria = new ControllerActionCriteria();
            //overviewCriteria.AddAction<MvcEngine.Blog.StarterSite.Controllers.BlogPostController>(a => a.Overview(0));
            //registry.Add(new[] { overviewCriteria }, typeof(PageActionFilter));

            //BackOffice
            ControllerCriteria moduleCriteria = new ControllerCriteria();
            moduleCriteria.AddController(typeof(MvcEngine.Blog.BackOffice.Controllers.BlogPostController));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.Edit(Guid.Empty, null, Guid.Empty));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.Index(Guid.Empty, null));
            ////moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.NewPost(Guid.Empty, null));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.Comments(null));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.OverviewSettings(0));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.DeleteComment(null, Guid.Empty));
            //moduleCriteria.AddAction<MvcEngine.Blog.BackOffice.Controllers.BlogPostController>(s => s.CreatePost(Guid.Empty, null, null, null, null));
            registry.Add(new[] { moduleCriteria }, new ModuleActionFilter());

            //--------------------------------------------------------------------------------------
            //---------------------------------Permissions------------------------------------------
            //--------------------------------------------------------------------------------------
            ControllerCriteria viewCriteria = new ControllerCriteria();
            viewCriteria.AddController(typeof(MvcEngine.Blog.StarterSite.Controllers.BlogPostController));

            ControllerCriteria editCriteria = new ControllerCriteria();
            editCriteria.AddController(typeof(MvcEngine.Blog.BackOffice.Controllers.BlogPostController));

            registry.Add(new[] { editCriteria }, new RolePermissionAttribute(Constants.Roles.Administrators));
            registry.Add(new[] { viewCriteria }, new ModulePermissionAttribute(PermissionTypes.View));

            //--------------------------------------------------------------------------------------
            //---------------------------------End of permissions----------------------------------
            //--------------------------------------------------------------------------------------
        }

        public override void RegisterModelBinders(ModelBinderDictionary binders)
        {
            binders[typeof(BlogPost)] = new BlogPostModelBinder();
            binders[typeof(BlogPostComment)] = new BlogPostCommentModelBinder();
        }

        public override Type GetControllerType()
        {
            return typeof(MvcEngine.Blog.StarterSite.Controllers.BlogPostController);
        }

        public override string GetDefaultAction()
        {
            return "Index";
        }
    }
}
